# This file is part of Howlr.
#
# Howlr is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Howlr is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Howlr.  If not, see <http://www.gnu.org/licenses/>.

require 'howlr/message'
require 'restr'

module Howlr::Controllers
  # Messages are created and delivered via this resource.
  class Messages < REST 'messages'
    # Contains a list of messages that were created.
    # Note that this is not persistent! This value is wiped when the server
    # is shut down.
    @@messages = []
    
    # Render a form for manually inputing a new message.
    def new
      render :new_message
    end
    
    # Show the message with the given id created by this server.
    def read(id)
      puts "Looking for #{id}"
      @message = @@messages.find{|m| m.id == id}
      puts @format
      if @message
        render :message
      else
        _error("There is no recently sent message with id #{id}.", 404)
      end
    end
    
    # Create and send a new message.
    def create
      if @input['rest'] == '1' && @input['0']
        # for PHP Zend_Rest_Client compatibility
        data = @input['0']
      else
        data = @input
      end
      
      data[:author] ||= @env['REMOTE_HOST']
      
      $LOG.debug "Creating new message from: #{data.inspect}"
      
      
      @message = Howlr::Message.new(data)
      $LOG.debug "Sending message: #{@message.inspect}"
      
      @@messages << @message
      
      begin
        @message.send
      rescue Howlr::Message::CallbackError => e
        return _error("Error while executing callback: #{e.underlying_error}", 500, e.underlying_error)
      rescue => e
        return _error("Error while sending message: #{e.message}", 500, e)
      end
      
      @headers['Location'] = "/messages/#{@message.id}?format=#{@format}"
      
      render :message
    end
  end
  
  # Can be used as a callback target for messages. This makes it possible
  # to receive a notification when a message is sent out.
  #
  # For example, set up your outgoing message's callback values as follows:
  #
  #   callback_url: http://howlr.example.com/delivery_notifications
  #   callback_method: post
  #
  # Now when the message is sent, a delivery notice will be sent back to
  # the sender, informing them of whether the message was successfully
  # sent out, or if some sort of delivery error occurred.
  #
  # The real-world usefulness of this is probably questionable. It's just
  # meant to illustrate how a message callback receiver can be implemented.
  class DeliveryNotifications < REST 'delivery_notifications'
    def create
      $LOG.debug "Creating delivery notification from: #{@input.inspect}"
      
      auth = {
        :username => Conf[:auth_username], 
        :password => Conf[:auth_password]
      }
      
      begin
        m = Restr.get("http://localhost:#{Conf[:port]}#{Conf[:uri_path]}messages", 
          {:id => @input[:message_id], :format => 'XML'}, 
          auth)
        
        to = m['from']
        subject = "Howlr Message Delivery Notification"
        
        body = "Your message regarding #{m['subject'].inspect} was " +
          (@input[:send_success] == 'true' ? '' : 'NOT') +
          " sent successfully to #{@input[:recipient_address]}."
        
        data = {
          :recipients => to, 
          :body => body, 
          :subject => subject,
          :from => @input[:recipient_address]
        }
        puts data.inspect
        Restr.post("http://localhost:#{Conf.port}#{Conf.uri_path}messages",
          data, auth)
          
      rescue Net::HTTPServerException, Net::HTTPError => e
        return _error($LAST_ERROR_BODY, e.response.code, e)
      rescue => e
        return _error(e.inspect, 500, e)
      end
    end
  end
end